package design.mode.factory;

/**
 * 抽象工厂模式（Abstract Factory Pattern）指提供一个创建一系列相关或相互依赖对象的接口，无须指定它们具体的类。
 * 意思是客户端不必指定产品的具体类型，创建多个产品族中的产品对象。<br/><br/>
 * 原文：Provide an interface for creating families of related ordependent objects without specifying their concrete classes.<br/><br/>
 * 在抽象工厂模式中，客户端（应用层）不依赖产品类实例如何被创建、实现等细节，
 * 强调一系列相关的产品对象（属于同一产品族）一起创建对象，需要大量重复的代码。
 * 需要提供一个产品类的库，所有产品以同样的接口出现，从而使客户端不依赖具体实现。
 */
public class AbstractFactoryPattern {

    /**
     * <br/>
     * 抽象工厂模式的优点：<br/>
     * （1）当需要产品族时，抽象工厂可以保证客户端始终只使用同一个产品的产品族。<br/>
     * （2）抽象工厂增强了程序的可扩展性，对于新产品族的增加，只需实现一个新的具体工厂即可，不需要对已有代码进行修改，符合开闭原则。<br/><br/>
     * 抽象工厂模式的缺点：<br/>
     * （1）规定了所有可能被创建的产品集合，产品族中扩展新的产品困难，需要修改抽象工厂的接口。<br/>
     * （2）增加了系统的抽象性和理解难度。<br/>
     *
     * @param args
     */
    public static void main(String[] args) {
        IFactory factory = new Factory01();
        factory.makeProductA().doA();
        factory.makeProductB().doB();

        factory = new Factory02();
        factory.makeProductA().doA();
        factory.makeProductB().doB();
    }

    /**
     * 抽象工厂（IAbstractFactory）：声明创建抽象产品对象的一个操作接口。
     */
    public interface IFactory{
        IProductA makeProductA();
        IProductB makeProductB();
    }

    /**
     * 产品A抽象
     */
    public interface IProductA{
        void doA();
    }


    /**
     * 产品B抽象
     */
    public interface IProductB{
        void doB();
    }

    // 抽象产品（IAbstractProduct）：为一类产品对象声明一个接口。

    /**
     * 只生产01型产品的工厂
     */
    static class Factory01 implements IFactory {

        @Override
        public IProductA makeProductA() {
            return new ProductA_01();
        }

        @Override
        public IProductB makeProductB() {
            return new ProductB_01();
        }
    }

    /**
     * 只生产02型产品的工厂
     */
    static class Factory02 implements IFactory {

        @Override
        public IProductA makeProductA() {
            return new ProductA_02();
        }

        @Override
        public IProductB makeProductB() {
            return new ProductB_02();
        }
    }

    /**
     * 产品A-01型号
     */
    static class ProductA_01 implements IProductA {

        @Override
        public void doA() {
            System.out.println("产品A-01型产品已生产就绪，开始运转！");
        }

    }

    /**
     * 产品A-02型号
     */
    static class ProductA_02 implements IProductA {

        @Override
        public void doA() {
            System.out.println("产品A-02型产品已生产就绪，开始运转！");
        }

    }

    /**
     * 产品B-01型号
     */
    static class ProductB_01 implements IProductB {

        @Override
        public void doB() {
            System.out.println("产品B-01型产品已生产就绪，开始运转！");
        }

    }

    /**
     * 产品B-02型号
     */
    static class ProductB_02 implements IProductB {

        @Override
        public void doB() {
            System.out.println("产品B-02型产品已生产就绪，开始运转！");
        }

    }

}
